/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package ar.edu.unicen.twitter.suggest.frontend.controllers;

import ar.edu.unicen.twitter.suggest.backend.datasources.TwitterFacade;
import ar.edu.unicen.twitter.suggest.backend.datasources.dao.ReportDao;
import ar.edu.unicen.twitter.suggest.backend.datasources.dao.TwitterDatasetDao;
import ar.edu.unicen.twitter.suggest.backend.dtos.RecommendationReport;
import ar.edu.unicen.twitter.suggest.backend.dtos.UsuarioProxy;
import ar.edu.unicen.twitter.suggest.backend.services.RecommendationControllerInterface;
import ar.edu.unicen.twitter.suggest.commons.dtos.Usuario;
import ar.edu.unicen.twitter.suggest.interfaces.exceptions.RejectedException;
import ar.edu.unicen.twitter.suggest.interfaces.exceptions.TwitterException;
import ar.edu.unicen.twitter.suggest.interfaces.exceptions.UserNotFoundException;
import ar.edu.unicen.twitter.suggest.interfaces.exceptions.UserProtectedException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Random;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;

/**
 *
 * @author Alex
 */
@Controller("holdOutController")
public class HoldOutController {

    @Autowired
    TwitterFacade twitterFacade;
    @Autowired
    ReportDao reportDao;
    @Autowired
    RecommendationControllerInterface recommendationController;
    @Autowired
    TwitterDatasetDao twitterDataset;
    private String screenName = "jasigno";
    private int holdoutRatio = 3;
    private int nivelIntermedio = 400;
    private int nivelFinal = 20;
    private int iteraciones = 1;
    private int MAXSEGUIDOS = 5000;
    private boolean permitirRedundancia = false;
    private List<RecommendationReport> reports;
    private Usuario usuario;
    private RecommendationReport reportAmigos;
    private RecommendationReport reportFuentes;
    private RecommendationReport reportUnion;
    private RecommendationReport reportInterseccion;
    static int max = 307517082;

    public HoldOutController() {
    }

    public void batchSearch() {


        int[] nodos = {800};
        int[] arcos = {5000};
        for (int a = 0; a < arcos.length; ++a) {
            for (int n = 0; n < nodos.length; ++n) {
                HashSet<Long> visitados = new HashSet<Long>();
                List<Usuario> abuscar = new ArrayList<Usuario>();
                int iteraciones = 3;
                int first = 1;
                int last = 560;
                for (int i = 1; i < first; ++i) {
                    visitados.add((long) i);
                }
                for (int i = first; i <= last; ++i) {
                    abuscar.add(twitterDataset.getUsuarioLazy(i));
                }
                while (!abuscar.isEmpty()) {
                    usuario = abuscar.get(0);
                    abuscar.remove(0);
                    if (usuario != null) {
                        if (!visitados.contains(usuario.getId()) && usuario.getFollowsCount() > 20 && usuario.getFollowsCount() < 600) {
                            System.out.println("intentando " + usuario);
                            int nIntermedio = nodos[n];
                            int maxSeguidos = arcos[a];
                            //List<RecommendationReport> reportesSinRedundancia = recommendationController.recomendar(usuario.getId(), nIntermedio, getNivelFinal(), maxSeguidos, iteraciones, 1.0f / holdoutRatio, false);
                            List<RecommendationReport> reportesConRedundancia = recommendationController.recomendar(usuario.getId(), nIntermedio, getNivelFinal(), maxSeguidos, iteraciones, 1.0f / holdoutRatio, true);
                            visitados.add(usuario.getId());
//                    if(!reportesSinRedundancia.isEmpty() && reportesSinRedundancia.get(0).getRecomendacion()!=null)
//                        abuscar.addAll(reportesSinRedundancia.get(0).getRecomendacion());
//                    if(reportesSinRedundancia.size()>1 && reportesSinRedundancia.get(1).getRecomendacion()!=null)
//                        abuscar.addAll(reportesSinRedundancia.get(1).getRecomendacion());


                        } else {
                            System.out.println("salteando " + usuario);
                        }
                    } else {
                        System.out.println("salteando " + usuario);
                    }
                }
            }
        }
    }

    public void search() {
        try {
            reports = new ArrayList<RecommendationReport>();
            setUsuario((UsuarioProxy) twitterFacade.getUser(getScreenName()));
            long usuarioId = 7475746;
            reports = recommendationController.recomendar(usuarioId, getNivelIntermedio(), getNivelFinal(), MAXSEGUIDOS, getIteraciones(), 1.0f / holdoutRatio, isPermitirRedundancia());
            for (RecommendationReport reporte : reports) {
                if (reporte.getMetodo() == RecommendationReport.METODO_AMIGOS) {
                    reportAmigos = reporte;
                } else if (reporte.getMetodo() == RecommendationReport.METODO_FUENTES) {
                    reportFuentes = reporte;
                } else if (reporte.getMetodo() == RecommendationReport.METODO_UNION) {
                    setReportUnion(reporte);
                } else if (reporte.getMetodo() == RecommendationReport.METODO_INTERSECCION) {
                    setReportInterseccion(reporte);
                }
            }
        } catch (UserNotFoundException ex) {
            Logger.getLogger(HoldOutController.class.getName()).log(Level.SEVERE, null, ex);
        } catch (UserProtectedException ex) {
            Logger.getLogger(HoldOutController.class.getName()).log(Level.SEVERE, null, ex);
        } catch (RejectedException ex) {
            Logger.getLogger(HoldOutController.class.getName()).log(Level.SEVERE, null, ex);
        } catch (TwitterException ex) {
            Logger.getLogger(HoldOutController.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    public String getScreenName() {
        return screenName;
    }

    public void setScreenName(String screenName) {
        this.screenName = screenName;
    }

    public int getHoldoutRatio() {
        return holdoutRatio;
    }

    public void setHoldoutRatio(int holdoutRatio) {
        this.holdoutRatio = holdoutRatio;
    }

    public int getNivelIntermedio() {
        return nivelIntermedio;
    }

    public void setNivelIntermedio(int nivelIntermedio) {
        this.nivelIntermedio = nivelIntermedio;
    }

    public int getNivelFinal() {
        return nivelFinal;
    }

    public void setNivelFinal(int nivelFinal) {
        this.nivelFinal = nivelFinal;
    }

    public int getIteraciones() {
        return iteraciones;
    }

    public void setIteraciones(int iteraciones) {
        this.iteraciones = iteraciones;
    }

    public List<RecommendationReport> getReports() {
        return reports;
    }

    public void setReports(List<RecommendationReport> reports) {
        this.reports = reports;
    }

    public Usuario getUsuario() {
        return usuario;
    }

    public void setUsuario(Usuario usuario) {
        this.usuario = usuario;
    }
//
//    private int[] getPosiciones(Collection<Usuario> subconjunto, List<Usuario> conjunto) {
//        int[] posiciones = new int[subconjunto.size()];
//        for (int p = 0; p < subconjunto.size(); ++p) {
//            posiciones[p] = RecommendationReport.POSICION_NO_ENCONTRADO;
//        }
//        int encontrados = 0;
//        int u = 0;
//        for (Usuario usuario : subconjunto) {
//            int p = conjunto.indexOf(usuario);
//            if (p != -1) {
//                posiciones[u++] = p;
//                encontrados++;
//            } else {
//                posiciones[u] = RecommendationReport.POSICION_NO_ENCONTRADO;
//            }
//        }
//        return posiciones;
//    }
//
//    private float[] getScore(List<Usuario> usuarios) {
//        float[] array = new float[usuarios.size()];
//        int d = 0;
//        for (Usuario u : usuarios) {
//            array[d++] = (float) u.getMentions();
//        }
//        return array;
//    }
//
//    private RecommendationReport generateReport(int metodo, Date start, long elapsedTime, RecolectorApi recolector,List<Usuario> usuariosTodos,List<Usuario> recomendacion, Collection<Usuario> descartados)
//    {
//        RecommendationReport report = new RecommendationReport();
//        report.setDate(start);
//        report.setElapsedTime(elapsedTime);
//        report.setMetodo(metodo);
//        if(recolector != null)
//        {
//            int nNiveles = recolector.getNiveles().size();
//            int nNodos = 0;
//            for (int nivel = 0; nivel < nNiveles; ++nivel) {
//                nNodos += recolector.getNiveles().get(nivel).getCrudo().size();
//            }
//            report.setRecuentoNodos(nNodos);
//        }
//        usuariosTodos= new ArrayList<Usuario>(usuariosTodos);
//        report.setRecomendacion(recomendacion);
//        report.setScore(getScore(recomendacion));
//        
//        report.setHoldout(descartados);
//        report.setPosicion(getPosiciones(descartados, usuariosTodos));
//        report.setRecuentoHojas(usuariosTodos.size());
//       
//        return report;
//    }

    public RecommendationReport getReportAmigos() {
        return reportAmigos;
    }

    public RecommendationReport getReportFuentes() {
        return reportFuentes;
    }

    public boolean isPermitirRedundancia() {
        return permitirRedundancia;
    }

    public void setPermitirRedundancia(boolean permitirRedundancia) {
        this.permitirRedundancia = permitirRedundancia;
    }

    public RecommendationReport getReportUnion() {
        return reportUnion;
    }

    public void setReportUnion(RecommendationReport reportUnion) {
        this.reportUnion = reportUnion;
    }

    public RecommendationReport getReportInterseccion() {
        return reportInterseccion;
    }

    public void setReportInterseccion(RecommendationReport reportInterseccion) {
        this.reportInterseccion = reportInterseccion;
    }
}
